home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / ntp_src / ntp_util.c < prev    next >
C/C++ Source or Header  |  1992-04-03  |  21KB  |  1,149 lines

  1. /* $Header: ntp_util.c,v 1.3 91/06/19 11:08:09 ath Exp $ */
  2. /*
  3.  * ntp_util.c - stuff I didn't have any other place for
  4.  */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8. #include <time.h>
  9.  
  10. #include "global.h"
  11. #include "sockaddr.h"
  12. #include "mbuf.h"        /* for {get,put}{16,32} */
  13. #include "netuser.h"
  14.  
  15. #include "ntp_types.h"
  16. #include "ntp_syslog.h"
  17. #include "ntp_fp.h"
  18. #include "ntp.h"
  19. #include "ntp_calendar.h"
  20.  
  21. /*
  22.  * This contains odds and ends.  Right now the only thing you'll find
  23.  * in here is the hourly stats printer and some code to support rereading
  24.  * the keys file, but I may eventually put other things in here such as
  25.  * code to do something with the leap bits.
  26.  */
  27.  
  28. #ifdef XNTP_AUTHENTICATE
  29. /*
  30.  * Name of the keys file
  31.  */
  32. char *key_file_name;
  33. #endif  /* XNTP_AUTHENTICATE */
  34.  
  35. #if 0                /* No drift file right now */
  36. /*
  37.  * The name of the drift_comp file and the temporary.
  38.  */
  39. char *stats_drift_file;
  40. char *stats_temp_file;
  41. #endif /* 0 */
  42.  
  43. /*
  44.  * We query the errno to see what kind of error occured
  45.  * when opening the drift file.
  46.  */
  47. extern int errno;
  48.  
  49. #ifdef DEBUG
  50. extern int debug;
  51. #endif
  52.  
  53. /*
  54.  * init_util - initialize the utilities
  55.  */
  56. void
  57. init_util()
  58. {
  59. #if 0
  60.     stats_drift_file = 0;
  61.     stats_temp_file = 0;
  62. #endif /* 0 */
  63. #ifdef  XNTP_AUTHENTICATE
  64.     key_file_name = 0;
  65. #endif
  66. }
  67.  
  68.  
  69. /*
  70.  * hourly_stats - print some interesting stats
  71.  */
  72. void
  73. hourly_stats()
  74. {
  75.     int fd;
  76.     char *val;
  77.     int vallen;
  78.     extern l_fp drift_comp;
  79.     extern long compliance;
  80.     extern char *lfptoa();
  81.     extern char *mfptoa();
  82.  
  83.     syslog(LOG_INFO, "hourly check: drift %s compliance %s",
  84.         lfptoa(&drift_comp, 8),
  85.         mfptoa((compliance<0)?(-1L):0L, compliance, 8));
  86.     
  87.     
  88. #if 0                /* no drift file for now in NOS */
  89.     if (stats_drift_file != 0) {
  90.         fd = open(stats_temp_file, O_WRONLY|O_TRUNC|O_CREAT, 0666);
  91.         if (fd == -1) {
  92.             syslog(LOG_ERR, "can't open %s: %m", stats_temp_file);
  93.             return;
  94.         }
  95.  
  96.         val = lfptoa(&drift_comp, 9);
  97.         vallen = strlen(val);
  98.         /*
  99.          * Hack here.  Turn the trailing \0 into a \n and write it.
  100.          */
  101.         val[vallen] = '\n';
  102.         if (write(fd, val, vallen+1) == -1) {
  103.             syslog(LOG_ERR, "write to %s failed: %m",
  104.                 stats_temp_file);
  105.             (void) close(fd);
  106.             (void) unlink(stats_temp_file);
  107.         } else {
  108.             (void) close(fd);
  109.             /* atomic */
  110.             (void) rename(stats_temp_file, stats_drift_file);
  111.         }
  112.     }
  113. #endif  /* 0 */
  114. }
  115.  
  116.  
  117. /*
  118.  * stats_config - configure the stats operation
  119.  */
  120. void
  121. stats_config(item, value)
  122.     int item;
  123.     char *value;    /* only one type so far */
  124. {
  125.     register char *cp;
  126.     FILE *fp;
  127.     int len;
  128. /*    char buf[128]; */
  129.     l_fp old_drift;
  130.     extern void loop_config();
  131.     extern char *lfptoa();
  132.  
  133.     switch(item) {
  134. #if 0                /* no drift file yet. */
  135.     case STATS_FREQ_FILE:
  136.         if (stats_drift_file != 0) {
  137.             (void) free(stats_drift_file);
  138.             (void) free(stats_temp_file);
  139.             stats_drift_file = 0;
  140.             stats_temp_file = 0;
  141.         }
  142.  
  143.         if (value == 0 || (len = strlen(value)) == 0)
  144.             break;
  145.  
  146.         stats_drift_file = emalloc((u_int)(len + 1));
  147.         stats_temp_file = emalloc((u_int)(len + sizeof(".TEMP")));
  148.         bcopy(value, stats_drift_file, len+1);
  149.         bcopy(value, stats_temp_file, len);
  150.         bcopy(".TEMP", stats_temp_file + len, sizeof(".TEMP"));
  151. #ifdef DEBUG
  152.         if (debug > 1) {
  153.             printf("stats drift file %s\n", stats_drift_file);
  154.             printf("stats temp file %s\n", stats_temp_file);
  155.         }
  156. #endif
  157.  
  158.         if ((fp = fopen(stats_drift_file, "r")) == NULL) {
  159.             if (errno != ENOENT)
  160.                 syslog(LOG_ERR, "can't open %s: %m",
  161.                     stats_drift_file);
  162.             break;
  163.         }
  164.  
  165.         if (fgets(buf, sizeof buf, fp) == NULL) {
  166.             syslog(LOG_ERR, "can't read %s: %m",
  167.                 stats_drift_file);
  168.             (void) fclose(fp);
  169.             break;
  170.         }
  171.  
  172.         (void) fclose(fp);
  173.  
  174.         /*
  175.          * We allow leading spaces, then the number.  Terminate
  176.          * at any trailing space or string terminator.
  177.          */
  178.         cp = buf;
  179.         while (isspace(*cp))
  180.             cp++;
  181.         while (*cp != '\0' && !isspace(*cp))
  182.             cp++;
  183.         *cp = '\0';
  184.  
  185.         if (!atolfp(buf, &old_drift)) {
  186.             syslog(LOG_ERR, "drift value %s invalid", buf);
  187.             break;
  188.         }
  189.  
  190.         /*
  191.          * Finally!  Give value to the loop filter.
  192.          */
  193. #ifdef DEBUG
  194.         if (debug > 1) {
  195.             printf("loop_config finds old drift of %s\n",
  196.                 lfptoa(&old_drift, 9));
  197.         }
  198. #endif
  199.         loop_config(LOOP_DRIFTCOMP, &old_drift);
  200.         break;
  201. #endif /* 0 */
  202.  
  203.     /* The drift value itself is passed in. */
  204.     case STATS_FREQ:
  205.         if (!atolfp(value, &old_drift)) {
  206.             tprintf("drift value %s invalid", value);
  207.             break;
  208.         }
  209.  
  210.         loop_config(LOOP_DRIFTCOMP, &old_drift);
  211.         break;
  212.  
  213.     default:
  214.         /* oh well */
  215.         break;
  216.     }
  217. }
  218.  
  219.  
  220. #ifdef XNTP_AUTHENTICATE
  221.  
  222. /*
  223.  * getauthkeys - read the authentication keys from the specified file
  224.  */
  225. void
  226. getauthkeys(keyfile)
  227.     char *keyfile;
  228. {
  229.     int len;
  230.  
  231.     len = strlen(keyfile);
  232.     if (len == 0)
  233.         return;
  234.     
  235.     if (key_file_name != 0) {
  236.         if (len > strlen(key_file_name)) {
  237.             (void) free(key_file_name);
  238.             key_file_name = 0;
  239.         }
  240.     }
  241.  
  242.     if (key_file_name == 0)
  243.         key_file_name = mallocw((u_int)(len + 1));
  244.     
  245.     bcopy(keyfile, key_file_name, len+1);
  246.  
  247.     authreadkeys(key_file_name);
  248. }
  249.  
  250.  
  251. /*
  252.  * rereadkeys - read the authentication key file over again.
  253.  */
  254. void
  255. rereadkeys()
  256. {
  257.     if (key_file_name != 0)
  258.         authreadkeys(key_file_name);
  259. }
  260.  
  261. #endif  /* XNTP_AUTHENTICATE */
  262.  
  263.  
  264. /* htons and friends, implemented using the equivalent NOS functions. */
  265. int16
  266. htons (h)
  267. int16 h;
  268. {
  269.     int16 n;
  270.     put16 ((char *)&n, h);
  271.     return n;
  272. }
  273.  
  274. int16
  275. ntohs (n)
  276. int16 n;
  277. {
  278.     return get16 ((char *)&n);
  279. }
  280.  
  281. int32
  282. htonl (h)
  283. int32 h;
  284. {
  285.     int32 n;
  286.     put32 ((char *)&n, h);
  287.     return n;
  288. }
  289.  
  290. int32
  291. ntohl (n)
  292. int32 n;
  293. {
  294.     return get32 ((char *)&n);
  295. }
  296.  
  297.  
  298. /*
  299.  * And here we have all the routines used by the NOS ntp code from xntp's
  300.  * library.  I didn't want to make yet another library for NOS.
  301.  */
  302.  
  303. /******
  304.  * ranny.c
  305.  */
  306.  
  307. /*
  308.  * Random number generator is:
  309.  *
  310.  *    Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
  311.  *    This will be free software, but only when it is finished.
  312.  *
  313.  * Used in xntp by permission of the author.  If copyright is
  314.  * annoying to you, read no further.  Instead, look up the reference,
  315.  * write me an equivalent to this and send it back to me.
  316.  */
  317.  
  318. /*
  319.  * Random number generator; see Knuth Vol 2. 2nd ed. p.27 (section 3.2.2)
  320.  */
  321.  
  322. /*
  323.  * 55 random numbers, not all even.  Note we don't initialize ran_y
  324.  * directly since I have had thoughts of putting this in an EPROM
  325.  */
  326. static u_long ran_y[55];
  327.  
  328. static u_long init_ran_y[55] = {
  329.     1860909544, 231033423, 437666411, 1349655137, 2014584962,
  330.     504613712, 656256107, 1246027206, 573713775, 643466871,
  331.     540235388, 1630565153, 443649364, 729302839, 1933991552,
  332.     944681982, 949111118, 406212522, 1065063137, 1712954727,
  333.     73280612, 787623973, 1874130997, 801658492, 73395958,
  334.     739165367, 596047144, 490055249, 1131094323, 662727104,
  335.     483614097, 844520219, 893760527, 921280508, 46691708,
  336.     760861842, 1425894220, 702947816, 2006889048, 1999607995,
  337.     1346414687, 399640789, 1482689501, 1790064052, 1128943628,
  338.     1269197405, 587262386, 2078054746, 1675409928, 1652325524,
  339.     1643525825, 1748690540, 292465849, 1370173174, 402865384
  340. };
  341.  
  342. static int ran_j;
  343. static int ran_k;
  344.  
  345.  
  346. /*
  347.  * ranp2 - return a random integer in the range 0 .. (1<<m)-1
  348.  */
  349. u_long
  350. ranp2(m)
  351.     int m;
  352. {
  353.     u_long r;
  354.  
  355.     ran_y[ran_k] += ran_y[ran_j];    /* overflow does a mod */
  356.     r = ran_y[ran_k];
  357.     if (ran_k-- == 0) ran_k = 54;
  358.     if (ran_j-- == 0) ran_j = 54;
  359.     return (r & ((1<<m)-1));
  360. }
  361.  
  362. #ifdef notdef
  363. /*
  364.  * ranny - return a random integer in the range 0 .. m-1
  365.  */
  366. u_long
  367. ranny(m)
  368.     u_int m;
  369. {
  370.     unsigned long r;
  371.  
  372.     ran_y[ran_k] += ran_y[ran_j];    /* overflow does a mod */
  373.     r = ran_y[ran_k];
  374.     if (ran_k-- == 0) ran_k = 54;
  375.     if (ran_j-- == 0) ran_j = 54;
  376.     return (r % m);
  377. }
  378. #endif /* notdef */
  379.  
  380. /*
  381.  * init_random - do initialization of random number routine
  382.  */
  383. void
  384. init_random()
  385. {
  386.     register int i;
  387.     register time_t now;
  388.  
  389.     ran_j = 23;
  390.     ran_k = 54;
  391.  
  392.     /*
  393.      * Randomize the seed array some more.  The time of day
  394.      * should be initialized by now.
  395.      */
  396.     now = (time_t)(time((time_t *)0))|01;
  397.  
  398.     for (i = 0; i < 55; ++i)
  399.         ran_y[i] = now * init_ran_y[i];    /* overflow does a mod */
  400. }
  401.  
  402. /* ntp passes ntoa a pointer to a sockaddr_in, and wants a char * back.
  403.  * NOS has inet_ntoa() which takes a long (in host byte order) and returns a
  404.  * char *.
  405.  */
  406. char *
  407. ntoa(addr)
  408. struct sockaddr_in *addr;
  409. {
  410.     return inet_ntoa (ntohl (addr->sin_addr.s_addr));
  411. }
  412.  
  413. /*
  414.  * lib_strbuf.h - definitions for routines which use the common string buffers
  415.  */
  416.  
  417. /*
  418.  * Sizes of things
  419.  */
  420. #define    LIB_NUMBUFS    5
  421. #define    LIB_BUFLENGTH    80
  422.  
  423. /*
  424.  * Macro to get a pointer to the next buffer
  425.  */
  426. #define    LIB_GETBUF(buf) \
  427.     do { \
  428.         buf = &lib_stringbuf[lib_nextbuf][0]; \
  429.         if (++lib_nextbuf >= LIB_NUMBUFS) \
  430.             lib_nextbuf = 0; \
  431.     } while (0)
  432.  
  433.  
  434. /*
  435.  * lib_strbuf - library string storage
  436.  */
  437.  
  438. /*
  439.  * Storage declarations
  440.  */
  441. char lib_stringbuf[LIB_NUMBUFS][LIB_BUFLENGTH];
  442. int lib_nextbuf;
  443.  
  444. /*
  445.  * initialization routine.  Might be needed if the code is ROMized.
  446.  */
  447. void
  448. init_lib()
  449. {
  450.     lib_nextbuf = 0;
  451. }
  452.  
  453.  
  454. /*
  455.  * lfptoa - return an asciized representation of a signed l_fp number
  456.  */
  457.  
  458. char *
  459. lfptoa(fpv, ndec)
  460.     l_fp *fpv;
  461.     int ndec;
  462. {
  463.     extern char *mfptoa();
  464.  
  465.     return mfptoa(fpv->l_ui, fpv->l_uf, ndec);
  466. }
  467.  
  468. /*
  469.  * atolfp - convert an ascii string to an l_fp number
  470.  */
  471.  
  472. /*
  473.  * Powers of 10
  474.  */
  475. static u_long ten_to_the_n[10] = {
  476.            0,
  477.           10,
  478.          100,
  479.         1000,
  480.            10000,
  481.           100000,
  482.          1000000,
  483.         10000000,
  484.        100000000,
  485.       1000000000,
  486. };
  487.  
  488.  
  489. int
  490. atolfp(str, lfp)
  491.     char *str;
  492.     l_fp *lfp;
  493. {
  494.     register char *cp;
  495.     register u_long dec_i;
  496.     register u_long dec_f;
  497.     char *ind;
  498.     int ndec;
  499.     int isneg;
  500.     static char *digits = "0123456789";
  501.  
  502.     isneg = 0;
  503.     dec_i = dec_f = 0;
  504.     ndec = 0;
  505.     cp = str;
  506.  
  507.     /*
  508.      * We understand numbers of the form:
  509.      *
  510.      * [spaces][-][digits][.][digits][spaces|\n|\0]
  511.      */
  512.     while (isspace(*cp))
  513.         cp++;
  514.     
  515.     if (*cp == '-') {
  516.         cp++;
  517.         isneg = 1;
  518.     }
  519.  
  520.     /* gdt */
  521.     if (*cp == '+') {
  522.         cp++;
  523.         isneg = 0;
  524.     }
  525.  
  526.     if (*cp != '.' && !isdigit(*cp))
  527.         return 0;
  528.  
  529. #define index strchr        /* ANSI C */
  530.     while (*cp != '\0' && (ind = index(digits, *cp)) != NULL) {
  531.         dec_i = (dec_i << 3) + (dec_i << 1);    /* multiply by 10 */
  532.         dec_i += (ind - digits);
  533.         cp++;
  534.     }
  535.  
  536.     if (*cp != '\0' && !isspace(*cp)) {
  537.         if (*cp++ != '.')
  538.             return 0;
  539.     
  540.         while (ndec < 9 && *cp != '\0'
  541.             && (ind = index(digits, *cp)) != NULL) {
  542.             ndec++;
  543.             dec_f = (dec_f << 3) + (dec_f << 1);    /* *10 */
  544.             dec_f += (ind - digits);
  545.             cp++;
  546.         }
  547.  
  548.         while (isdigit(*cp))
  549.             cp++;
  550.         
  551.         if (*cp != '\0' && !isspace(*cp))
  552.             return 0;
  553.     }
  554.  
  555.     if (ndec > 0) {
  556.         register u_long tmp;
  557.         register u_long bit;
  558.         register u_long ten_fact;
  559.  
  560.         ten_fact = ten_to_the_n[ndec];
  561.  
  562.         tmp = 0;
  563.         bit = 0x80000000;
  564.         while (bit != 0) {
  565.             dec_f <<= 1;
  566.             if (dec_f >= ten_fact) {
  567.                 tmp |= bit;
  568.                 dec_f -= ten_fact;
  569.             }
  570.             bit >>= 1;
  571.         }
  572.         if ((dec_f << 1) > ten_fact)
  573.             tmp++;
  574.         dec_f = tmp;
  575.     }
  576.  
  577.     if (isneg)
  578.         M_NEG(dec_i, dec_f);
  579.     
  580.     lfp->l_ui = dec_i;
  581.     lfp->l_uf = dec_f;
  582.     return 1;
  583. }
  584.  
  585.  
  586. /*
  587.  * umfptoa - Return an asciized representation of an unsigned long fp number
  588.  */
  589. char *
  590. umfptoa(fpi, fpf, ndec)
  591.     u_long fpi;
  592.     u_long fpf;
  593.     int ndec;
  594. {
  595.     extern char *dolfptoa();
  596.  
  597.     return dolfptoa(fpi, fpf, 0, ndec, 0);
  598. }
  599.  
  600. /*
  601.  * mfptoa - Return an asciized representation of a signed long fp number
  602.  */
  603. char *
  604. mfptoa(fpi, fpf, ndec)
  605.     u_long fpi;
  606.     u_long fpf;
  607.     int ndec;
  608. {
  609.     int isneg;
  610.     extern char *dolfptoa();
  611.  
  612.     if (M_ISNEG(fpi, fpf)) {
  613.         isneg = 1;
  614.         M_NEG(fpi, fpf);
  615.     } else
  616.         isneg = 0;
  617.  
  618.     return dolfptoa(fpi, fpf, isneg, ndec, 0);
  619. }
  620.  
  621. /*
  622.  * fptoa - return an asciized representation of an s_fp number
  623.  */
  624. char *
  625. fptoa(fpv, ndec)
  626.     s_fp fpv;
  627.     int ndec;
  628. {
  629.     u_fp plusfp;
  630.     int neg;
  631.     extern char *dofptoa();
  632.  
  633.     if (fpv < 0) {
  634.         plusfp = (u_fp)(-fpv);
  635.         neg = 1;
  636.     } else {
  637.         plusfp = (u_fp)fpv;
  638.         neg = 0;
  639.     }
  640.  
  641.     return dofptoa(plusfp, neg, ndec, 0);
  642. }
  643.  
  644. /*
  645.  * ufptoa - return an asciized representation of an u_fp number
  646.  */
  647.  
  648. char *
  649. ufptoa(fpv, ndec)
  650.     u_fp fpv;
  651.     int ndec;
  652. {
  653.     extern char *dofptoa();
  654.  
  655.     return dofptoa(fpv, 0, ndec, 0);
  656. }
  657.  
  658.  
  659. /*
  660.  * ufptoms - return an asciized u_fp number in milliseconds
  661.  */
  662. char *
  663. ufptoms(fpv, ndec)
  664.     u_fp fpv;
  665.     int ndec;
  666. {
  667.     extern char *dofptoa();
  668.  
  669.     return dofptoa(fpv, 0, ndec, 1);
  670. }
  671.  
  672.  
  673. /*
  674.  * ulfptoms - return an asciized unsigned l_fp number in milliseconds
  675.  */
  676. char *
  677. ulfptoms(fpv, ndec)
  678.     l_fp *fpv;
  679.     int ndec;
  680. {
  681.     extern char *umfptoms();
  682.  
  683.     return umfptoms(fpv->l_ui, fpv->l_uf, ndec);
  684. }
  685.  
  686. /*
  687.  * lfptoms - return an asciized signed l_fp number in milliseconds
  688.  */
  689. char *
  690. lfptoms(fpv, ndec)
  691.     l_fp *fpv;
  692.     int ndec;
  693. {
  694.     extern char *mfptoms();
  695.  
  696.     return mfptoms(fpv->l_ui, fpv->l_uf, ndec);
  697. }
  698.  
  699. /*
  700.  * fptoms - return an asciized s_fp number in milliseconds
  701.  */
  702. char *
  703. fptoms(fpv, ndec)
  704.     s_fp fpv;
  705.     int ndec;
  706. {
  707.     u_fp plusfp;
  708.     int neg;
  709.     extern char *dofptoa();
  710.  
  711.     if (fpv < 0) {
  712.         plusfp = (u_fp)(-fpv);
  713.         neg = 1;
  714.     } else {
  715.         plusfp = (u_fp)fpv;
  716.         neg = 0;
  717.     }
  718.  
  719.     return dofptoa(plusfp, neg, ndec, 1);
  720. }
  721.  
  722.  
  723. /*
  724.  * numtoa - return asciized network numbers store in local array space
  725.  */
  726. char *
  727. numtoa(num)
  728.     u_long num;
  729. {
  730.     register u_long netnum;
  731.     register char *buf;
  732.  
  733.     netnum = ntohl(num);
  734.     LIB_GETBUF(buf);
  735.  
  736.     (void) sprintf(buf, "%d.%d.%d.%d", (int)((netnum>>24)&0xff),
  737.                (int)((netnum>>16)&0xff), (int)((netnum>>8)&0xff),
  738.                (int)(netnum&0xff));
  739.  
  740.     return buf;
  741. }
  742.  
  743.  
  744. /*
  745.  * atoint - convert an ascii string to a signed long, with error checking
  746.  */
  747. int
  748. atoint(str, ival)
  749.     char *str;
  750.     long *ival;
  751. {
  752.     register u_long u;
  753.     register char *cp;
  754.     register int isneg;
  755.     register int oflow_digit;
  756.  
  757.     cp = str;
  758.  
  759.     if (*cp == '-') {
  760.         cp++;
  761.         isneg = 1;
  762.         oflow_digit = '8';
  763.     } else {
  764.         isneg = 0;
  765.         oflow_digit = '7';
  766.     }
  767.  
  768.     if (*cp == '\0')
  769.         return 0;
  770.  
  771.     u = 0;
  772.     while (*cp != '\0') {
  773.         if (!isdigit(*cp))
  774.             return 0;
  775.         if (u > 214748364 || (u == 214748364 && *cp > oflow_digit))
  776.             return 0;    /* overflow */
  777.         u = (u << 3) + (u << 1);
  778.         u += *cp++ - '0';    /* ascii dependent */
  779.     }
  780.  
  781.     if (isneg)
  782.         *ival = -((long)u);
  783.     else 
  784.         *ival = (long)u;
  785.     return 1;
  786. }
  787.  
  788.  
  789. /*
  790.  * mfptoms - Return an asciized signed long fp number in milliseconds
  791.  */
  792. char *
  793. mfptoms(fpi, fpf, ndec)
  794.     u_long fpi;
  795.     u_long fpf;
  796.     int ndec;
  797. {
  798.     int isneg;
  799.     extern char *dolfptoa();
  800.  
  801.     if (M_ISNEG(fpi, fpf)) {
  802.         isneg = 1;
  803.         M_NEG(fpi, fpf);
  804.     } else
  805.         isneg = 0;
  806.  
  807.     return dolfptoa(fpi, fpf, isneg, ndec, 1);
  808. }
  809.  
  810. /*
  811.  * umfptoms - Return an asciized unsigned long fp number in milliseconds
  812.  */
  813. char *
  814. umfptoms(fpi, fpf, ndec)
  815.     u_long fpi;
  816.     u_long fpf;
  817.     int ndec;
  818. {
  819.     extern char *dolfptoa();
  820.  
  821.     return dolfptoa(fpi, fpf, 0, ndec, 1);
  822. }
  823.  
  824. /*
  825.  * dolfptoa - do the grunge work of converting an l_fp number to decimal
  826.  */
  827. char *
  828. dolfptoa(fpi, fpv, neg, ndec, msec)
  829.     u_long fpi;
  830.     u_long fpv;
  831.     int neg;
  832.     int ndec;
  833.     int msec;
  834. {
  835.     register u_char *cp, *cpend;
  836.     register u_long work_i;
  837.     register int dec;
  838.     u_char cbuf[24];
  839.     u_char *cpdec;
  840.     char *buf;
  841.     char *bp;
  842.  
  843.     /*
  844.      * Get a string buffer before starting
  845.      */
  846.     LIB_GETBUF(buf);
  847.  
  848.     /*
  849.      * Zero the character buffer
  850.      */
  851.     bzero(cbuf, sizeof(cbuf));
  852.  
  853.     /*
  854.      * Work on the integral part.  This is biased by what I know
  855.      * compiles fairly well for a 68000.
  856.      */
  857.     cp = cpend = &cbuf[10];
  858.     work_i = fpi;
  859.     if (work_i & 0xffff0000) {
  860.         register u_long lten = 10;
  861.         register u_long ltmp;
  862.  
  863.         do {
  864.             ltmp = work_i;
  865.             work_i /= lten;
  866.             ltmp -= (work_i<<3) + (work_i<<1);
  867.             *--cp = (u_char)ltmp;
  868.         } while (work_i & 0xffff0000);
  869.     }
  870.     if (work_i != 0) {
  871.         register u_short sten = 10;
  872.         register u_short stmp;
  873.         register u_short swork = (u_short)work_i;
  874.  
  875.         do {
  876.             stmp = swork;
  877.             swork /= sten;
  878.             stmp -= (swork<<3) + (swork<<1);
  879.             *--cp = (u_char)stmp;
  880.         } while (swork != 0);
  881.     }
  882.  
  883.     /*
  884.      * Done that, now deal with the problem of the fraction.  First
  885.      * determine the number of decimal places.
  886.      */
  887.     if (msec) {
  888.         dec = ndec + 3;
  889.         if (dec < 3)
  890.             dec = 3;
  891.         cpdec = &cbuf[13];
  892.     } else {
  893.         dec = ndec;
  894.         if (dec < 0)
  895.             dec = 0;
  896.         cpdec = &cbuf[10];
  897.     }
  898.     if (dec > 12)
  899.         dec = 12;
  900.     
  901.     /*
  902.      * If there's a fraction to deal with, do so.
  903.      */
  904.     if (fpv != 0) {
  905.         register u_long work_f;
  906.  
  907.         work_f = fpv;
  908.         while (dec > 0) {
  909.             register u_long tmp_i;
  910.             register u_long tmp_f;
  911.  
  912.             dec--;
  913.             /*
  914.              * The scheme here is to multiply the
  915.              * fraction (0.1234...) by ten.  This moves
  916.              * a junk of BCD into the units part.
  917.              * record that and iterate.
  918.              */
  919.             work_i = 0;
  920.             M_LSHIFT(work_i, work_f);
  921.             tmp_i = work_i;
  922.             tmp_f = work_f;
  923.             M_LSHIFT(work_i, work_f);
  924.             M_LSHIFT(work_i, work_f);
  925.             M_ADD(work_i, work_f, tmp_i, tmp_f);
  926.             *cpend++ = (u_char)work_i;
  927.             if (work_f == 0)
  928.                 break;
  929.         }
  930.  
  931.         /*
  932.          * Rounding is rotten
  933.          */
  934.         if (work_f & 0x80000000) {
  935.             register u_char *tp = cpend;
  936.  
  937.             *(--tp) += 1;
  938.             while (*tp >= 10) {
  939.                 *tp = 0;
  940.                 *(--tp) += 1;
  941.             };
  942.             if (tp < cp)
  943.                 cp = tp;
  944.         }
  945.     }
  946.     cpend += dec;
  947.  
  948.  
  949.     /*
  950.      * We've now got the fraction in cbuf[], with cp pointing at
  951.      * the first character, cpend pointing past the last, and
  952.      * cpdec pointing at the first character past the decimal.
  953.      * Remove leading zeros, then format the number into the
  954.      * buffer.
  955.      */
  956.     while (cp < cpdec) {
  957.         if (*cp != 0)
  958.             break;
  959.         cp++;
  960.     }
  961.     if (cp == cpdec)
  962.         --cp;
  963.  
  964.     bp = buf;
  965.     if (neg)
  966.         *bp++ = '-';
  967.     while (cp < cpend) {
  968.         if (cp == cpdec)
  969.             *bp++ = '.';
  970.         *bp++ = (char)(*cp++ + '0');    /* ascii dependent? */
  971.     }
  972.     *bp = '\0';
  973.  
  974.     /*
  975.      * Done!
  976.      */
  977.     return buf;
  978. }
  979.  
  980.  
  981. /*
  982.  * dofptoa - do the grunge work to convert an fp number to ascii
  983.  */
  984. char *
  985. dofptoa(fpv, neg, ndec, msec)
  986.     u_fp fpv;
  987.     int neg;
  988.     int ndec;
  989.     int msec;
  990. {
  991.     register u_char *cp, *cpend;
  992.     register u_long val;
  993.     register short dec;
  994.     u_char cbuf[12];
  995.     u_char *cpdec;
  996.     char *buf;
  997.     char *bp;
  998.  
  999.     /*
  1000.      * Get a string buffer before starting
  1001.      */
  1002.     LIB_GETBUF(buf);
  1003.  
  1004.     /*
  1005.      * Zero out the buffer
  1006.      */
  1007.     bzero((char *)cbuf, sizeof cbuf);
  1008.  
  1009.     /*
  1010.      * Set the pointers to point at the first
  1011.      * decimal place.  Get a local copy of the value.
  1012.      */
  1013.     cp = cpend = &cbuf[5];
  1014.     val = fpv;
  1015.  
  1016.     /*
  1017.      * If we have to, decode the integral part
  1018.      */
  1019.     if (!(val & 0xffff0000))
  1020.         cp--;
  1021.     else {
  1022.         register u_short sv = (u_short)(val >> 16);
  1023.         register u_short tmp;
  1024.         register u_short ten = 10;
  1025.  
  1026.         do {
  1027.             tmp = sv;
  1028.             sv /= ten;
  1029.             *(--cp) = tmp - ((sv<<3) + (sv<<1));
  1030.         } while (sv != 0);
  1031.     }
  1032.  
  1033.     /*
  1034.      * Figure out how much of the fraction to do
  1035.      */
  1036.     if (msec) {
  1037.         dec = ndec + 3;
  1038.         if (dec < 3)
  1039.             dec = 3;
  1040.         cpdec = &cbuf[8];
  1041.     } else {
  1042.         dec = ndec;
  1043.         cpdec = cpend;
  1044.     }
  1045.  
  1046.     if (dec > 6)
  1047.         dec = 6;
  1048.     
  1049.     if (dec > 0) {
  1050.         do {
  1051.             val &= 0xffff;
  1052.             val = (val << 3) + (val << 1);
  1053.             *cpend++ = (u_char)(val >> 16);
  1054.         } while (--dec > 0);
  1055.     }
  1056.  
  1057.     if (val & 0x8000) {
  1058.         register u_char *tp;
  1059.         /*
  1060.          * Round it. Ick.
  1061.          */
  1062.         tp = cpend;
  1063.         *(--tp) += 1;
  1064.         while (*tp >= 10) {
  1065.             *tp = 0;
  1066.             *(--tp) += 1;
  1067.         }
  1068.     }
  1069.  
  1070.     /*
  1071.      * Remove leading zeroes if necessary
  1072.      */
  1073.     while (cp < (cpdec -1) && *cp == 0)
  1074.         cp++;
  1075.     
  1076.     /*
  1077.      * Copy it into the buffer, asciizing as we go.
  1078.      */
  1079.     bp = buf;
  1080.     if (neg)
  1081.         *bp++ = '-';
  1082.     
  1083.     while (cp < cpend) {
  1084.         if (cp == cpdec)
  1085.             *bp++ = '.';
  1086.         *bp++ = (char)(*cp++ + '0');
  1087.     }
  1088.     *bp = '\0';
  1089.     return buf;
  1090. }
  1091.  
  1092.  
  1093. /*
  1094.  * calleapwhen - determine the number of seconds to the next possible
  1095.  *         leap occurance and the last one.
  1096.  */
  1097.  
  1098. /*
  1099.  * calleaptab - leaps occur at the end of December and June
  1100.  */
  1101. static long calleaptab[10] = {
  1102.     -(JAN+FEBLEAP)*SECSPERDAY,    /* leap previous to cycle */
  1103.     (MAR+APR+MAY+JUN)*SECSPERDAY,    /* end of June */
  1104.     (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY, /* end of Dec */
  1105.     (MAR+APR+MAY+JUN)*SECSPERDAY + SECSPERYEAR,
  1106.     (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + SECSPERYEAR,
  1107.     (MAR+APR+MAY+JUN)*SECSPERDAY + 2*SECSPERYEAR,
  1108.     (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + 2*SECSPERYEAR,
  1109.     (MAR+APR+MAY+JUN)*SECSPERDAY + 3*SECSPERYEAR,
  1110.     (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY + 3*SECSPERYEAR,
  1111.     (MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC+JAN+FEBLEAP+MAR+APR+MAY+JUN)
  1112.         *SECSPERDAY + 3*SECSPERYEAR,    /* next after current cycle */
  1113. };
  1114.  
  1115. void
  1116. calleapwhen(ntpdate, leaplast, leapnext)
  1117.     u_long ntpdate;
  1118.     u_long *leaplast;
  1119.     u_long *leapnext;
  1120. {
  1121.     register u_long dateincycle;
  1122.     register int i;
  1123.  
  1124.     /*
  1125.      * Find the offset from the start of the cycle
  1126.      */
  1127.     dateincycle = ntpdate;
  1128.     if (dateincycle >= MAR1988)
  1129.         dateincycle -= MAR1988;
  1130.     else
  1131.         dateincycle -= MAR1900;
  1132.  
  1133.     while (dateincycle >= SECSPERCYCLE)
  1134.         dateincycle -= SECSPERCYCLE;
  1135.  
  1136.     /*
  1137.      * Find where we are with respect to the leap events.
  1138.      */
  1139.     for (i = 1; i < 9; i++)
  1140.         if (dateincycle < (u_long)calleaptab[i])
  1141.             break;
  1142.     
  1143.     /*
  1144.      * i points at the next leap.  Compute the last and the next.
  1145.      */
  1146.     *leaplast = (u_long)((long)dateincycle - calleaptab[i-1]);
  1147.     *leapnext = (u_long)(calleaptab[i] - (long)dateincycle);
  1148. }
  1149.